import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;

/**
 * Represents test article as sequence of sentences.
 */
public class Article extends TextElement
{
    /**
     * Sequence of sentences.
     */
    public Sentence[] sentences;

    public Article(File xmlFile) throws Throwable
    {
        // Parse XML to DOM document
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();

        document = builder.parse(xmlFile);

        id = xmlFile.getName(); // last component
        fullFilename = xmlFile.getAbsolutePath();

        // get list of sentence XML elements
        Element corpusElement = document.getDocumentElement();
        Element articleElement = (Element) corpusElement.getChildNodes().item(0);
        Element paragraphElement = (Element) articleElement.getChildNodes().item(0);
        NodeList sentencesNodes = paragraphElement.getChildNodes();

        // recursively build sentence list
        sentences = new Sentence[sentencesNodes.getLength()];
        for (int i = 0; i < sentencesNodes.getLength(); i++)
        {
            Element sentenceElem = (Element) sentencesNodes.item(i);
            sentences[i] = new Sentence(sentenceElem, this);
        }
    }

    /**
     * Count token error statistics.
     */
    public Stats CountStats()
    {
        Stats stats = new Stats();
        for (Sentence sentence : sentences)
            for (Token token : sentence.tokens)
            {
                stats.total++;
                if (token.GetStatus() == Token.Status.UNDEFINED)
                    stats.undefined++;
                else if (token.GetStatus() == Token.Status.ERROR)
                    stats.error++;
            }
        return stats;
    }

    /**
     * Save changes back to XML file.
     */
    public void SaveXML() throws Throwable
    {
        Source source = new DOMSource(document);
        File file = new File(this.fullFilename);
        Result result = new StreamResult(file);
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.transform(source, result);
    }

    /**
     * Save full path to parsed file in order to write changes later.
     */
    private String fullFilename;
}
